/**
 * 文件名：****.java
 * 版权：Copyright Lightkit All Rights Reserved.
 * 描述：*****
 */
package com.lightkits.wms.domain.allot.impl;

import com.lightkits.common.MessageUtil;
import com.lightkits.common.TransactionValidate;
import com.lightkits.common.db.entity.FndOrganizationBase;
import com.lightkits.common.db.entity.FndWorker;
import com.lightkits.common.db.entity.WmExecuteLine;
import com.lightkits.common.db.entity.WmRequestHeader;
import com.lightkits.common.db.entity.WmRequestLine;
import com.lightkits.common.db.entity.event.BdEvent;
import com.lightkits.common.db.entity.event.BdEventRecord;
import com.lightkits.framework.common.exception.LightKitsBizException;
import com.lightkits.framework.common.logging.Logger;
import com.lightkits.framework.common.logging.LoggerFactory;
import com.lightkits.framework.common.model.CheckResult;
import com.lightkits.framework.common.model.IResult;
import com.lightkits.framework.common.utility.json.JsonUtil;
import com.lightkits.framework.common.utility.object.ObjectUtil;
import com.lightkits.framework.common.utility.object.ParseUtil;
import com.lightkits.framework.common.utility.validate.IntegrityValidator;
import com.lightkits.wms.domain.allot.CreateDocParamsService;
import com.lightkits.wms.domain.allot.CreateEventParamsService;
import com.lightkits.wms.domain.allot.CreateOnhAndTagService;
import com.lightkits.wms.domain.allot.UseAllotParamsService;
import com.lightkits.wms.domain.allot.UseAllotReceiveParamsService;
import com.lightkits.wms.domain.commons.service.WmsCommonsService;
import com.lightkits.wms.domain.nontaskpickinglist.repo.WmRequestHeaderService;
import com.lightkits.wms.domain.nontaskpickinglist.repo.WmRequestLineService;
import com.lightkits.wms.domain.rawmatstorage.repo.WmExecuteLineService;
import com.lightkits.wms.domain.saveonhand.repo.BdEventRecordService;
import com.lightkits.wms.domain.saveonhand.repo.BdEventService;
import com.lightkits.wms.domain.stocktransfer.service.OrgSubStockTransDomain;
import com.lightkits.wms.domain.tagservice.UseTagParamsService;
import com.lightkits.wms.dto.allot.model.PickHeadDto;
import com.lightkits.wms.dto.allot.model.PickLineDto;
import com.lightkits.wms.dto.stocktransfer.model.OrgSubStockViewDto;
import com.lightkits.wms.dto.tagservice.model.TagViewDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * 调拨接收
 *
 * @author jing.wei@hand-china.com
 * @date 2019/5/28 15:46
 **/
@Service
public class UseAllotReceiveParamsServiceImpl implements UseAllotReceiveParamsService {
    private final OrgSubStockTransDomain orgSubStockTransDomain;
    private final UseAllotParamsService useAllotParamsService;

    @Autowired
    public UseAllotReceiveParamsServiceImpl(WmsCommonsService wmsCommonsService,
                                            CreateDocParamsService docParamsService,
                                            CreateEventParamsService eventParamsService,
                                            CreateOnhAndTagService onhAndTagService,
                                            BdEventService bdEventService,
                                            BdEventRecordService bdEventRecordService,
                                            WmRequestHeaderService wmRequestHeaderService,
                                            WmRequestLineService wmRequestLineService,
                                            WmExecuteLineService wmExecuteLineService,
                                            UseTagParamsService useTagParamsService,
                                            OrgSubStockTransDomain orgSubStockTransDomain,
                                            UseAllotParamsService useAllotParamsService) {
        this.docParamsService = docParamsService;
        this.eventParamsService = eventParamsService;
        this.onhAndTagService = onhAndTagService;
        this.bdEventService = bdEventService;
        this.bdEventRecordService = bdEventRecordService;
        this.wmRequestHeaderService = wmRequestHeaderService;
        this.wmRequestLineService = wmRequestLineService;
        this.wmExecuteLineService = wmExecuteLineService;
        this.useTagParamsService = useTagParamsService;
        this.orgSubStockTransDomain = orgSubStockTransDomain;
        this.useAllotParamsService = useAllotParamsService;
    }

    private final UseTagParamsService useTagParamsService;
    private final BdEventService bdEventService;
    private final BdEventRecordService bdEventRecordService;
    private final WmRequestHeaderService wmRequestHeaderService;
    private final WmRequestLineService wmRequestLineService;
    private final WmExecuteLineService wmExecuteLineService;

    private final CreateDocParamsService docParamsService;
    private final CreateEventParamsService eventParamsService;
    private final CreateOnhAndTagService onhAndTagService;
    private static final Logger LOGGER =
            LoggerFactory.getLogger(UseAllotReceiveParamsServiceImpl.class);

    /**
     * 调拨接收参数校验
     *
     * @param headDto     调拨参数头
     * @param lineDtoList 调拨单行
     * @return IResult
     **/
    private IResult checkPaerams(PickHeadDto headDto, List<PickLineDto> lineDtoList) {
        try {
            //headDto参数必输校验
            IntegrityValidator.begin()
                    .validate(headDto.getOrgId(), "Organization Id")
                    .validate(headDto.getToOrganzationId(), "To Organization Id");
            //headDto参数有效性校验
            TransactionValidate check = TransactionValidate
                    .beginValidity(FndOrganizationBase.class);
            check.checkIdValidity(
                    ObjectUtil.toString(headDto.getToOrganzationId()),
                    "ORGANIZATION_ID");
            check = TransactionValidate
                    .beginValidity(FndOrganizationBase.class);
            check.checkIdValidity(
                    ObjectUtil.toString(headDto.getOrgId()),
                    "ORGANIZATION_ID");

            IResult result = IResult.fail(MessageUtil.getSysMessage("NO_OR_INVALID"));
            if (!ObjectUtil.isNullOrEmpty(headDto.getCreatorId())) {
                FndWorker worker = new FndWorker()
                        .selectById(headDto.getCreatorId());
                if (worker == null || worker.getOrganizationId()
                        .equals(headDto.getToOrganzationId())) {
                    return result;
                }
            }
            if (!ObjectUtil.isNullOrEmpty(headDto.getRequestWorkerId())) {
                FndWorker worker = new FndWorker()
                        .selectById(headDto.getRequestWorkerId());
                if (worker == null || worker.getOrganizationId()
                        .equals(headDto.getToOrganzationId())) {
                    return result;
                }
            }
        } catch (LightKitsBizException e) {
            return e.result();
        }
        //发出与接受组织不能相同的校验
        if (headDto.getOrgId().equals(headDto.getToOrganzationId())) {
            return IResult.fail(
                    MessageUtil
                            .getSysMessage("TO_ORG_CANNOT_SAME_WITH_FROM_ORG"));
        }
        useAllotParamsService.checkLines(lineDtoList, headDto.getOrgId(), headDto.getToOrganzationId());
        return IResult.success();
    }

    /**
     * 调拨接收
     *
     * @param headDto  调拨参数头
     * @param lineDtos 调拨单行
     * @return IResult
     **/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public IResult allotReceive(PickHeadDto headDto, List<PickLineDto> lineDtos) {
        IResult result = this.checkPaerams(headDto, lineDtos);
        if (!result.isSuccessful()) {
            return result;
        }
        //Create Bd Event
        CheckResult checkResult = eventParamsService.createEvent(headDto, "", "WM_ALLOT_IN");
        if (!checkResult.isSuccessful() || checkResult.getData() == null) {
            throw new LightKitsBizException(checkResult.getMessage());
        }
        BdEvent bdEvent = (BdEvent) checkResult.getData();
        boolean eventFlag = bdEventService.insert(bdEvent);
        if (!eventFlag) {
            throw new LightKitsBizException("Insert Event Failed");
        }
        List<BdEventRecord> bdEventRecords = new ArrayList<>();
        //Create Wm_Request_Header
        WmRequestHeader requestHeader = new WmRequestHeader().selectById(headDto.getRequestHeaderId());
        requestHeader.setProcessStatus("RECEIVED");
        requestHeader.setToOrganizationId(
                ParseUtil.tryLongWithException(headDto.getToOrganzationId()));
        boolean headerFlag = wmRequestHeaderService.updateById(requestHeader);
        if (!headerFlag) {
            throw new LightKitsBizException("Update Wm Request Header Failed");
        }
        //create header Record
        bdEventRecords.add(convertRecord(bdEvent.getId(),
                "WM_REQUEST_HEADER",
                requestHeader.getId(),
                JsonUtil.toString(requestHeader)
        ));
        //create Wm_request_line
        List<WmRequestLine> lines = new ArrayList<>();
        lineDtos.forEach(lineDto -> {
            WmRequestLine line = new WmRequestLine().selectById(lineDto.getRequestLineId());
            line.setConfirmedQty(line.getExeutedQty());
            line.setToWarehouseId(ParseUtil.tryLongWithException(lineDto.getToWarehouseId()));
            if (!ObjectUtil.isNullOrEmpty(lineDto.getToAreaId())) {
                line.setToWmAreaId(ParseUtil.tryLongWithException(lineDto.getToAreaId()));

            }
            if (!ObjectUtil.isNullOrEmpty(lineDto.getToLocationId())) {
                line.setToLocationId(ParseUtil.tryLongWithException(lineDto.getToLocationId()));

            }
            line.setLineStatus("RECEIVED");
            lines.add(line);
        });
        if (!ObjectUtil.isNullOrEmpty(lines)) {
            boolean linesFlag = wmRequestLineService.updateBatchById(lines);
            if (!linesFlag) {
                throw new LightKitsBizException("Update Wm Request Lines Failed");
            }
        }

        //create lines Records
        lines.forEach(line -> {
            bdEventRecords.add(convertRecord(bdEvent.getId(),
                    "WM_REQUEST_LINE",
                    line.getId(),
                    JsonUtil.toString(line)));
        });
        //create Wm_Execute_Line
        checkResult = docParamsService.createExecuteLine(lines, requestHeader.getId(), bdEvent.getId());
        if (!checkResult.isSuccessful() || checkResult.getData() == null) {
            throw new LightKitsBizException(checkResult.getMessage());
        }
        List<WmExecuteLine> exeLines = (List<WmExecuteLine>) checkResult.getData();
        boolean exeLinesFlag = wmExecuteLineService.insertBatch(exeLines);
        if (!exeLinesFlag) {
            throw new LightKitsBizException("Insert Wm Execute Lines Failed");
        }
        boolean recordsFlag = bdEventRecordService.insertBatch(bdEventRecords);
        if (!recordsFlag) {
            throw new LightKitsBizException("Insert Records Failed");
        }
        //OrgSubstockTransfer
        checkResult = onhAndTagService.createOrgSubStockParam(headDto, lineDtos);
        if (!checkResult.isSuccessful() || checkResult.getData() == null) {
            throw new LightKitsBizException(checkResult.getMessage());
        }
        List<OrgSubStockViewDto> subStockViewDTOS =
                (List<OrgSubStockViewDto>) checkResult.getData();
        subStockViewDTOS.forEach(sub -> {
            sub.setParentEventId(bdEvent.getId().toString());
            IResult iResult = orgSubStockTransDomain.orgSubStockTrans(sub);
            if (!iResult.isSuccessful()) {
                throw new LightKitsBizException(iResult.getMessage());
            }
        });
        //TagChange
        checkResult = onhAndTagService.createTags(lines, bdEvent, "RECEIVED", headDto.getToOrganzationId());
        if (!checkResult.isSuccessful() || checkResult.getData() == null) {
            throw new LightKitsBizException(checkResult.getMessage());
        }
        List<TagViewDto> tagViewDTOS =
                (List<TagViewDto>) checkResult.getData();

        IResult iResult = useTagParamsService.insertValue(tagViewDTOS);
        if (!iResult.isSuccessful()) {
            throw new LightKitsBizException(iResult.getMessage());
        }


        return IResult.success();
    }

    /**
     * 事件快照转换
     *
     * @param event          事件ID
     * @param objectType     类型
     * @param objectId       事件对象ID
     * @param snapShopRecord 事件记录
     * @return BdEventRecord
     **/
    private BdEventRecord convertRecord(Long event,
                                        String objectType,
                                        Long objectId,
                                        String snapShopRecord) {

        CheckResult<BdEventRecord> result = eventParamsService.createEventRecord(objectType,
                "",
                objectId,
                "",
                snapShopRecord);
        if (!result.isSuccessful() || result.getData() == null) {
            throw new LightKitsBizException(result.getMessage());
        }
        BdEventRecord record = result.getData();
        record.setEventId(event);
        return result.getData();

    }
}
